package com.luo.d3s.light.jpa.ec.domain.goods;

import com.luo.d3s.light.jpa.ec.application.dto.command.GoodsModifyCommand;
import com.luo.d3s.light.jpa.ec.domain.base.BaseEntity;
import com.luo.d3s.light.jpa.ec.domain.base.BizId;
import com.luo.d3s.light.jpa.ec.domain.base.Price;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

/**
 * 商品
 *
 * @author luohq
 * @date 2022-11-27 18:06
 */
@Entity
public class Goods extends BaseEntity {

    /**
     * 商品标签集合
     */
    @ElementCollection
    @CollectionTable(name = "goods_tag_binding", joinColumns = {@JoinColumn(name = "goods_id")})
    @AttributeOverride(name = "id", column = @Column(name = "tag_id", nullable = false))
    private Set<BizId> tagIds = new HashSet<>();

    /**
     * 商品所属分类
     */
    @Embedded
    @AttributeOverride(name = "id", column = @Column(name = "category_id"))
    @NotNull
    private BizId categoryId;

    /**
     * 商品名称
     */
    @Embedded
    @NotNull
    private GoodsName goodsName;

    /**
     * 商品描述
     */
    @Embedded
    @NotNull
    private GoodsSpec goodsSpec;

    /**
     * 商品价格
     */
    @Embedded
    @AttributeOverride(name = "price", column = @Column(name = "goods_price"))
    @NotNull
    private Price goodsPrice;

    /**
     * 商品状态
     */
    @NotNull
    private GoodsStatus goodsStatus;

    private Goods() {
    }

    /**
     * 初始创建商品信息
     *
     * @param id          商品ID
     * @param categoryId  商品所属分类ID
     * @param goodsName   商品名称
     * @param goodsSpec   商品描述
     * @param goodsPrice  商品价格
     * @param goodsStatus 商品状态
     */
    public Goods(BizId id, BizId categoryId, GoodsName goodsName, GoodsSpec goodsSpec, Price goodsPrice, GoodsStatus goodsStatus, Set<BizId> tagIds) {
        this.id = id;
        this.categoryId = categoryId;
        this.goodsName = goodsName;
        this.goodsSpec = goodsSpec;
        this.goodsPrice = goodsPrice;
        this.goodsStatus = goodsStatus;
        this.createTime = LocalDateTime.now();
        this.updateTime = this.createTime;
        Optional.ofNullable(tagIds).ifPresent(this.tagIds::addAll);
        this.validateSelf();
    }

    /**
     * 修改基础信息
     *
     * @param categoryId 分类ID
     * @param goodsName  商品名称
     * @param goodsSpec  商品规格
     * @param goodsPrice 商品价格
     */
    public void modifyBasicInfo(BizId categoryId, GoodsName goodsName, GoodsSpec goodsSpec, Price goodsPrice, Set<BizId> tagIds) {
        this.categoryId = categoryId;
        this.goodsName = goodsName;
        this.goodsSpec = goodsSpec;
        this.goodsPrice = goodsPrice;
        this.updateTime = LocalDateTime.now();
        this.tagIds.clear();
        Optional.ofNullable(tagIds).ifPresent(this.tagIds::addAll);
        this.validateSelf();
    }

    /**
     * 根据修改命令修改基础信息
     *
     * @param goodsModifyCommand 修改命令
     */
    public void modifyBasicInfo(GoodsModifyCommand goodsModifyCommand) {
        this.categoryId = BizId.fromValue(goodsModifyCommand.getCategoryId());
        this.goodsName = new GoodsName(goodsModifyCommand.getGoodsName());
        this.goodsSpec = GoodsSpec.builder()
                .manufactureDate(goodsModifyCommand.getManufactureDate())
                .expirationDate(goodsModifyCommand.getExpirationDate())
                .goodsWeight(GoodsWeight.builder()
                        .weight(goodsModifyCommand.getGoodsWeight())
                        .unit(WeightUnit.of(goodsModifyCommand.getGoodsWeightUnit()))
                        .build())
                .goodsDesc(goodsModifyCommand.getGoodsDesc())
                .build();
        this.goodsPrice = new Price(goodsModifyCommand.getGoodsPrice());
        this.updateTime = LocalDateTime.now();
        this.tagIds.clear();
        this.tagIds.addAll(BizId.fromNullableValues(goodsModifyCommand.getTagIds()));
        this.validateSelf();
    }

    /**
     * 上架商品
     */
    public void shelve() {
        this.goodsStatus = GoodsStatus.SHELVED;
    }

    /**
     * 下架商品
     */
    public void unshelve() {
        this.goodsStatus = GoodsStatus.UNSHELVED;
    }

    public BizId getCategoryId() {
        return categoryId;
    }

    public GoodsName getGoodsName() {
        return goodsName;
    }

    public GoodsSpec getGoodsSpec() {
        return goodsSpec;
    }

    public Price getGoodsPrice() {
        return goodsPrice;
    }

    public GoodsStatus getGoodsStatus() {
        return goodsStatus;
    }

    public Set<BizId> getTagIds() {
        return tagIds;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "id=" + id +
                ", categoryId=" + categoryId +
                ", goodsName=" + goodsName +
                ", goodsSpec=" + goodsSpec +
                ", goodsPrice=" + goodsPrice +
                ", goodsStatus=" + goodsStatus +
                ", tagIds=" + tagIds +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                '}';
    }
}
